package com.fingersoft.im;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;

import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.fingersoft.business.BusinessContext;
import com.fingersoft.business.app.IAppBehaviorListener;
import com.fingersoft.business.im.IIMProvider;
import com.fingersoft.cycle.ActivityCycleManager;
import com.fingersoft.cycle.IActivityCycle;
import com.fingersoft.dexload.PreLoadDexActivity;
import com.fingersoft.feature.faceId.FaceIDExport;
import com.fingersoft.feature.faceId.SealFaceIDCallback;
import com.fingersoft.feature.login.LoginActivity;
import com.fingersoft.feature.login.LoginSecondStyleActivity;
import com.fingersoft.feature.newlock.LockContext;
import com.fingersoft.feature.newlock.LockManager;
import com.fingersoft.feature.personal.ui.ChangePasswordActivity;
import com.fingersoft.feature.personal.ui.FindBackPasswordActivity;
import com.fingersoft.feature.personal.ui.ResetPasswordActivity;
import com.fingersoft.feature.sensitiveword.SealSensitiveWordContext;
import com.fingersoft.feature.sensitiveword.SensitiveWordContext;
import com.fingersoft.feature.webview.CordovaWebViewActivity;
import com.fingersoft.feature.webview.WebViewActivity0;
import com.fingersoft.feature.webview.WebViewActivity1;
import com.fingersoft.feature.webview.WebViewActivity2;
import com.fingersoft.feature.webview.WebViewActivity3;
import com.fingersoft.feature.webview.WebViewActivity4;
import com.fingersoft.im.api.UserAgent;
import com.fingersoft.im.base.MyActivityManager;
import com.fingersoft.im.feature.aiassistant.DaggerApplication;
import com.fingersoft.im.ui.LoadingActivity;
import com.fingersoft.im.ui.SplashActivity;
import com.fingersoft.im.utils.AppConfigUtils;
import com.fingersoft.im.utils.AppUtils;
import com.fingersoft.im.utils.JSONUtils;
import com.fingersoft.im.utils.LogUtils;
import com.fingersoft.im.utils.MultiLanguageUtil;
import com.fingersoft.im.view.LoadDialog;
import com.fingersoft.util.AppEventType;
import com.fingersoft.util.AppEventUtil;
import com.fingersoft.util.DeviceHelper;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.cache.CacheEntity;
import com.lzy.okgo.cache.CacheMode;
import com.lzy.okgo.cookie.store.PersistentCookieStore;
import com.lzy.okgo.model.HttpHeaders;
import com.lzy.okgo.model.HttpParams;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import cn.fingersoft.im.common.navigation.ActivityFragmentKt;
import cn.fingersoft.util.BuildConfigUtil;

import static com.fingersoft.im.utils.AppUtils.getVPNAddress;
import static com.fingersoft.im.utils.AppUtils.getVPNNtlsAddress;
import static com.fingersoft.im.utils.AppUtils.getVPNPassword;
import static com.fingersoft.im.utils.AppUtils.getVPNUsername;
import static com.fingersoft.im.utils.AppUtils.useLock;
import static com.fingersoft.im.utils.AppUtils.useVPN;
import static com.fingersoft.im.utils.AppUtils.useVoiceAssistant;


/**
 * Created by jameson on 4/21/16.
 */
public abstract class MyApplication extends DaggerApplication {
    protected static String PLUGIN_NAMES = BuildConfig.PLUGIN_NAMES;
    protected int mFinalCount;
    private int time = 0;
    protected static boolean isLock = false;
    Timer timer;
    SharedPreferences preferences;
    private List<IActivityCycle> all_cycles = new ArrayList<>(0);
    List<IActivityCycle> cycles = new ArrayList<>(0);
    private final String ACTION_VPN_CONFIG = "action_vpn_config";
    private final String ACTION_QUIT = "action_quit";
    private boolean canDisconnectVpn = true;

    public boolean isCanDisconnectVpn() {
        return canDisconnectVpn;
    }

    public void setCanDisconnectVpn(boolean canDisconnectVpn) {
        this.canDisconnectVpn = canDisconnectVpn;
    }

    public MyApplication() {
        Log.println(Log.INFO, "application", "application MyApplication..............");
    }

    /**
     * 调整初始化先后顺序或者位置时需要注意,有可能造成运行错误,会产生闪退日志
     */
    public abstract void appInitBeforeConfig();

    public void appInitAfterConfig() {
        Log.println(Log.INFO, "application", "application appInitAfterConfig..............");

        BusinessContext.Companion.onAppConfigInited(this);
        IIMProvider im = BusinessContext.Companion.getIm();
        if (im != null) {
            im.onAppConfigInited(this);
        }

        //人脸识别faceID初始化
        FaceIDExport.Companion.moduleInit(new SealFaceIDCallback());

        if (useVoiceAssistant() || "true".equals(BuildConfig.useAIAssistantBaidu)) {
            if (null != BusinessContext.Companion.getAppConfigInfo() &&
                BusinessContext.Companion.getAppConfigInfo().isYuyinEnabled()) {
                if (null != BusinessContext.Companion.getMVoiceAssistant()) {
                    BusinessContext.Companion.getMVoiceAssistant().init(
                        BusinessContext.Companion.getAppConfigInfo().isYuyinEnabled()
                        , BusinessContext.Companion.getAppConfigInfo().getYuyinAwakenWord()
                        , BusinessContext.Companion.getAppConfigInfo().getYuyin_baidu_app_id()
                        , BusinessContext.Companion.getAppConfigInfo().getYuyin_baidu_app_key()
                        , BusinessContext.Companion.getAppConfigInfo().getYuyin_baidu_app_secret());
                }
            }
        }
        SensitiveWordContext.init(this, new SealSensitiveWordContext());
    }


    /**
     * 获取初始化配置
     */
    public void initBasicAppInfo() {
        if(AppUtils.isUsingSolidKey() && null != BusinessContext.Companion.getDeviceVerify()){
            BusinessContext.Companion.getDeviceVerify().registerSlidKeyReceiver(this);
        }
        Log.i(TAG, "initBasicAppInfo()");
        boolean result = AppConfigUtils.getAppConfigSync(this);
        Log.i(TAG, "initBasicAppInfo:getAppConfigSync result is:" + result);
        if (result) {
            appInitAfterConfig();
        } else {
            if (useVPN() && BuildConfigUtil.INSTANCE.getString("setVPN_ConnectMode", "").contains("demand")) {
                registVPNBroadcastReceiver(this);
                BusinessContext.Companion.getMVPNProvider().init(getVPNAddress(), getVPNUsername(), getVPNPassword(), getVPNNtlsAddress());
            } else {
                //Toast.makeText(this, "更新应用配置失败", Toast.LENGTH_LONG).show();
                appInitAfterConfig();
            }
        }
    }


    protected void addActivityLifeCallbackListener() {
        registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {

            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                LogUtils.i("" + activity.getClass().getName());
                MyActivityManager.getInstance().add(activity);
                ActivityCycleManager.Companion.onCreate("All", activity, savedInstanceState);

                if (!MultiLanguageUtil.isAutoBySystem(activity)) {
                    if (!MultiLanguageUtil.isSameWithSetting(activity)) {
                        MultiLanguageUtil.changeAppLanguage(activity, MultiLanguageUtil.makeAppLocale(), false);
                    }
                }
            }

            @Override
            public void onActivityStarted(Activity activity) {
                LogUtils.i("" + activity.getClass().getName());
                if (ActivityFragmentKt.isActivityFragment(activity)) {
                    return;
                }
                mFinalCount++;
                //如果mFinalCount ==1，说明是从后台到前台
                checkApp2Foreground(activity.getClass().getName());
                if(BuildConfigUtil.INSTANCE.getBoolean("enableAutoScreenOrientation")) {
                    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
                }
            }

            @Override
            public void onActivityResumed(Activity activity) {
                MyActivityManager.getInstance().remove(activity);
                MyActivityManager.getInstance().add(activity);
                for (IActivityCycle cycle : all_cycles) {
                    cycle.onResume(activity);
                }
                ActivityCycleManager.Companion.onResume("All", activity);
                checkLock2foreground(activity.getClass().getName());
            }

            @Override
            public void onActivityPaused(Activity activity) {
                LogUtils.i("" + activity.getClass().getName());
                ActivityCycleManager.Companion.onPause("All", activity);
            }

            @Override
            public void onActivityStopped(Activity activity) {
                if (ActivityFragmentKt.isActivityFragment(activity)) {
                    return;
                }
                mFinalCount--;
                LogUtils.i("" + activity.getClass().getName());
                checkLock2background(activity.getClass().getName());
                checkApp2Background();
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
                LogUtils.i("" + activity.getClass().getName());
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                LogUtils.i("" + activity.getClass().getName());
                MyActivityManager.getInstance().remove(activity);
                ActivityCycleManager.Companion.onDestroy("All", activity);
                List remainActivitis = MyActivityManager.getInstance().getActivityList();
                if (remainActivitis.size() <= 0 && isCanDisconnectVpn()) {//断开vpn连接
                    try {
                        BusinessContext.Companion.getMVPNProvider().disconnectVPN();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    protected void checkLock2background(String activityClassName) {
        //切换到后台开始锁屏计时
        if (0 == getFinalCount() && useLock()) {
            if (LockManager.Companion.getInstance().isSetLock()) {
                if (!inSkipActivityList(activityClassName)) {
                    timer = new Timer();
                    time = (int)(AppConfigUtils.getAppConfigInfo(this).getPassword_use_minutes() * 60);
                    TimerTask tt = new TimerTask() {
                        @Override
                        public void run() {
                            time--;
                            Log.i("Lock", time + "s");
                            if (time <= 0) {
                                isLock = true;
                                time = Integer.MAX_VALUE;
                                if (timer != null) {
                                    timer.cancel();
                                }
                            }
                        }
                    };
                    timer.schedule(tt, 0, 1000);
                }
            }
        }
    }

    protected abstract int getFinalCount();


    protected void checkLock2foreground(String activityClassName) {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
        //如果锁屏时间到,那需要弹出锁屏页面
        if (isLock) {
            if (useLock()) {
                if (LockManager.Companion.getInstance().isSetLock()) {
                    if (!inSkipActivityList(activityClassName)) {
                        Activity secLastActivity = MyActivityManager.getInstance().getSecLastActivity();
                        if (secLastActivity != null) {
                            if (secLastActivity.getClass().getName().equals(LoginActivity.class.getName())) {
                                return;
                            }
                        }
                        isLock = false;
                        if (LockManager.Companion.getInstance().isSetLock()) {
                            LockContext.instance.onModuleCreate(getAppContext());
                            LockManager.Companion.getInstance().doUnLock(LockManager.Companion.getLOCK_TYPE_AUTO());
                        }
                    } else {
                        isLock = false;
                    }
                }
            }
        }
    }

    private boolean inSkipActivityList(String activityClassName) {
        final ArrayList<String> ignoreActivityNameList = BusinessContext.Companion.getLockIgnoreActivityNameList();
        List<String> skipActivityNames = new ArrayList<>();
        skipActivityNames.add(PreLoadDexActivity.class.getName());
        skipActivityNames.add(LoginActivity.class.getName());
        skipActivityNames.add(LoginSecondStyleActivity.class.getName());
        skipActivityNames.add(LoadingActivity.class.getName());
        skipActivityNames.add(FindBackPasswordActivity.class.getName());
        skipActivityNames.add(ChangePasswordActivity.class.getName());
        skipActivityNames.add(ResetPasswordActivity.class.getName());
        skipActivityNames.add(SplashActivity.class.getName());
        if (!BuildConfigUtil.INSTANCE.getBoolean("useLockForWebview", false)) {
            skipActivityNames.add(WebViewActivity0.class.getName());
            skipActivityNames.add(WebViewActivity1.class.getName());
            skipActivityNames.add(WebViewActivity2.class.getName());
            skipActivityNames.add(WebViewActivity3.class.getName());
            skipActivityNames.add(WebViewActivity4.class.getName());
            skipActivityNames.add(CordovaWebViewActivity.class.getName());
        }
        return ignoreActivityNameList.contains(activityClassName) || skipActivityNames.contains(activityClassName);
    }

    protected void checkApp2Foreground(String activityName) {
        if (getFinalCount() == 1) {
            //说明从后台回到了前台
            AppEventUtil.writeLandingState(AppEventType.App2Foreground);
            if (null != BusinessContext.Companion.getMVoiceAssistant()) {
                BusinessContext.Companion.getMVoiceAssistant().onAppToForeground(activityName);
            }
            for (IAppBehaviorListener listener : BusinessContext.Companion.getAppBehaviorListeners()) {
                listener.onApp2Foreground();
            }
            reConnectSocket();
        }
    }

    public boolean checkApp2Background() {
        //如果mFinalCount ==0，说明是前台到后台
        if (getFinalCount() == 0) {
            //说明从前台回到了后台
            AppEventUtil.writeLandingState(AppEventType.App2Background);
            showToastWhenApp2Background();
            if (null != BusinessContext.Companion.getMVoiceAssistant()) {
                BusinessContext.Companion.getMVoiceAssistant().onAppToBackground();
            }
            for (IAppBehaviorListener listener : BusinessContext.Companion.getAppBehaviorListeners()) {
                listener.onApp2Background();
            }
            return true;
        }
        return false;
    }

    abstract protected void reConnectSocket();

    private Context getAppContext() {
        return this;
    }

    protected void showToastWhenApp2Background() {

    }

    protected void initOkGo() {
        //必须调用初始化
        OkGo.init(this);

        HttpHeaders headers = new HttpHeaders();
        UserAgent.defaultInstance = new UserAgent("", "");
        UserAgent.defaultInstance.emp_version = AppUtils.getString("codeVersion", "");
        headers.put("Content-Type", "application/json");
//            headers.put("WorkUser-Agent", JSONUtils.toJsonString(new UserAgent(UserInfoManager.INSTANCE.getCurrentUserInfo().getUsertoken(), AppUtils.getTokenInfo().getDid())));
        headers.put("Emp-Info", JSONUtils.toJsonString(new UserAgent(this, AppUtils.getTokenInfo().getUserToken(), DeviceHelper.getDeviceID(this))));
        HttpParams params = new HttpParams();

        //-----------------------------------------------------------------------------------//
        try {
            //打开该调试开关,控制台会使用 红色error 级别打印log,并不是错误,是为了显眼,不需要就不要加入该行.
            //这个版本的okgo有bug,开启debug会导致docx,pptx等文件下载失败.https://github.com/jeasonlzy/okhttp-OkGo/issues/246
            //OkGo.getInstance().debug("OkGo");

            //以下都不是必须的，根据需要自行选择,一般来说只需要 debug,缓存相关,cookie相关的 就可以了
            OkGo okGo = OkGo.getInstance()
                //如果使用默认的 60秒,以下三行也不需要传
                .setConnectTimeout(10 * 1000)  //全局的连接超时时间
                .setReadTimeOut(30 * 60 * 1000)     //全局的读取超时时间
                .setWriteTimeOut(30 * 60 * 1000)    //全局的写入超时时间

                //可以全局统一设置缓存模式,默认是不使用缓存,可以不传,具体其他模式看 github 介绍 https://github.com/jeasonlzy/
                .setCacheMode(CacheMode.FIRST_CACHE_THEN_REQUEST)

                //可以全局统一设置缓存时间,默认永不过期,具体使用方法看 github 介绍
                .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE)

                //可以全局统一设置超时重连次数,默认为三次,那么最差的情况会请求4次(一次原始请求,三次重连请求),不需要可以设置为0
                .setRetryCount(0)

                //如果不想让框架管理cookie,以下不需要
//                .setCookieStore(new MemoryCookieStore())                //cookie使用内存缓存（app退出后，cookie消失）
                .setCookieStore(new PersistentCookieStore())          //cookie持久化存储，如果cookie不过期，则一直有效

                //可以设置https的证书,以下几种方案根据需要自己设置,不需要不用设置
//                .setCertificates()                                  //方法一：信任所有证书
//                    .setCertificates(getAssets().open("srca.cer"))      //方法二：也可以自己设置https证书
//                    .setCertificates(getAssets().open("aaaa.bks"), "123456", getAssets().open("srca.cer"))//方法三：传入bks证书,密码,和cer证书,支持双向加密

                //可以添加全局拦截器,不会用的千万不要传,错误写法直接导致任何回调不执行
//                .addInterceptor(new Interceptor() {
//                    @Override
//                    public Response intercept(Chain chain) throws IOException {
//                        return chain.proceed(chain.request());
//                    }
//                })

                //这两行同上,不需要就不要传
                .addCommonHeaders(headers)                                         //设置全局公共头
                .addCommonParams(params);                                          //设置全局公共参数

            if (BuildConfigUtil.INSTANCE.getBoolean("useSSLTrustManager")) {
                okGo.setCertificates(getAssets().open("cert.crt"));
            } else {
                okGo.setCertificates();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void onICreate() {
        Log.i(TAG, "onICreate()");
        initBasicAppInfo();
    }

    private LocalBroadcastManager broadcastManager;
    private BroadcastReceiver broadcastReceiver;
    private String TAG = "MyApplication";

    protected void registVPNBroadcastReceiver(Context context) {
        Log.i(TAG, "registVPNBroadcastReceiver");
        broadcastManager = LocalBroadcastManager.getInstance(context);
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Log.i(TAG, "registVPNBroadcastReceiver.BroadcastReceiver().onReceive");
                if (null != intent) {
                    if (intent.getAction().equals(ACTION_QUIT)) {
                        killProcess();
                    } else if (intent.getAction().equals(ACTION_VPN_CONFIG)) {
                        int vpnResult = intent.getIntExtra("result", 0);
                        if (0 != vpnResult) {
                            onICreate();
                            LoadDialog.dismiss(context);
//                            broadcastManager.unregisterReceiver(broadcastReceiver);
//                            broadcastManager = null;
//                            broadcastReceiver = null;
                        }
                    }
                }
            }
        };
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ACTION_VPN_CONFIG);
        intentFilter.addAction(ACTION_QUIT);
        broadcastManager.registerReceiver(broadcastReceiver, intentFilter);
    }

    protected static final byte[] lock = new byte[0];

    protected static class DexInstallDeamonThread extends Thread {

        private Handler handler;

        private Context base;

        private Looper looper;

        public DexInstallDeamonThread(Context base) {
            this.base = base;
        }

        @SuppressLint("HandlerLeak")
        @Override
        public void run() {
            Looper.prepare();
            looper = Looper.myLooper();
            handler = new Handler() {
                @SuppressWarnings("deprecation")
                @Override
                public void handleMessage(Message msg) {
                    synchronized (lock) {
                        lock.notify();
                    }
                }
            };

            Messenger messenger = new Messenger(handler);
            Intent intent = new Intent(base, PreLoadDexActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.putExtra("MESSENGER", messenger);
            intent.putExtra("useVideoInSplash", true);
            base.startActivity(intent);
            Looper.loop();
        }

        public void exit() {
            if (looper != null) {
                looper.quit();
            }
        }
    }

    protected void lockWait() {
        try {
            if (null != lock) {
                lock.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    protected void killProcess() {
        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(0);
    }
}
